package com.zxp.juc.jmm;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

/**
 * 知识点：线程上下文切换、缓存一致性协议mesi
 * @author ：shollin
 */
public class VolatileVisibilitySample {
    private boolean initFlag = false; // volatile
    static Object object = new Object();

    public void refresh(){
        this.initFlag = true; //普通写操作，(volatile写)
        String threadname = Thread.currentThread().getName();
        System.out.println("线程："+threadname+":修改共享变量initFlag");
    }

    @SneakyThrows
    public void load(){
        String threadname = Thread.currentThread().getName();
        int i = 0;
        while (!initFlag){
            /*synchronized (object){
                i++;
            }*/

            // 测试结果：当空转时,没有线程上下文切换,不会重新加载initFlag;
            // 如果initFlag被volatile修饰，在编译时会加上#lock，为保证缓存一致性协议，嗅探缓存行的变化
            // 当有延时操作时, 会有线程上下文切换,会加载initFlag到工作内存当中
            // Thread.sleep(100);
            ++i;

        }
        System.out.println("线程："+threadname+"当前线程嗅探到initFlag的状态的改变"+i);
    }

    public static void main(String[] args){
        VolatileVisibilitySample sample = new VolatileVisibilitySample();
        Thread threadA = new Thread(()->{
            sample.refresh();
        },"threadA");

        Thread threadB = new Thread(()->{
            sample.load();
        },"threadB");

        threadB.start();
        try {
             Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadA.start();
    }

}
